Skip to content

feat(desktop): integrate Datadog#14755

Draft
gre-ledger wants to merge 3 commits intodevelopfrom
support/desktop-datadog
Draft

feat(desktop): integrate Datadog#14755
gre-ledger wants to merge 3 commits intodevelopfrom
support/desktop-datadog

Conversation

@gre-ledger
Copy link
Contributor

@gre-ledger gre-ledger commented Feb 24, 2026

✅ Checklist

  • npx changeset was attached.
  • Covered by automatic tests.
  • Impact of the changes:
    • ...

📝 Description

  • client-ids DatadogId and UserId integration ( some integrated from feat(client-ids): encapsulate UserId & DatadogId to implement explicit id usage #13325 )

  • Datadog RUM (desktop)

    • Init in renderer (opt-in when lldDatadog + Sentry logs enabled).
    • Main process errors forwarded to renderer and sent as RUM errors.
    • Feature flag lldDatadog: sessionSamplingRate, sessionReplaySampleRate (default 0).
    • User id: DatadogId (UUID v4) stored on user and passed to RUM.
    • Parity with Sentry: ignore list, beforeSend, breadcrumbs, anonymization.
  • Sourcemaps

    • Upload step in tools/dist when DATADOG_API_KEY is set (service/release-version/minified prefix).
    • ledger-live-build: DATADOG_API_KEY set in release-desktop and pre-desktop workflows (macOS, Linux, Windows) so CI runs the upload.

Sentry unchanged; both run in parallel.

❓ Context


🧐 Checklist for the PR Reviewers

  • The code aligns with the requirements described in the linked JIRA or GitHub issue.
  • The PR description clearly documents the changes made and explains any technical trade-offs or design decisions.
  • There are no undocumented trade-offs, technical debt, or maintainability issues.
  • The PR has been tested thoroughly, and any potential edge cases have been considered and handled.
  • Any new dependencies have been justified and documented.
  • Performance considerations have been taken into account. (changes have been profiled or benchmarked if necessary)

@live-github-bot live-github-bot bot added desktop Has changes in LLD common Has changes in live-common ledgerjs Has changes in the ledgerjs open source libs labels Feb 24, 2026
@live-github-bot
Copy link
Contributor

live-github-bot bot commented Feb 24, 2026

Desktop Bundle Checks

Comparing e348a5b against af56e6e.

⚠️ renderer bundle size significantly increased: 25.9mb -> 26.1mb. Please check if this is expected.

Mobile Bundle Checks

Comparing e348a5b against af56e6e.

✅ Previous issues have all been fixed.

@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch 2 times, most recently from 507e5df to 0a768b6 Compare February 24, 2026 16:56
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch 15 times, most recently from 4f80f69 to 30d2f1d Compare February 27, 2026 17:11
@gre-ledger gre-ledger requested a review from Copilot February 27, 2026 17:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Datadog RUM instrumentation to Ledger Live Desktop (renderer + main error forwarding), while extending the shared @ledgerhq/client-ids library to manage/persist UserId and DatadogId and exposing a new lldDatadog feature flag configuration.

Changes:

  • Add Desktop Datadog RUM init/tagging + forward main-process errors to renderer for reporting.
  • Extend @ledgerhq/client-ids identities store to include userId/datadogId, persistence, selectors, and init/migration helper on desktop.
  • Update build/test scaffolding (env injection globals, Jest globals) and add @datadog/browser-rum dependency.

Reviewed changes

Copilot reviewed 48 out of 51 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
pnpm-lock.yaml Locks @datadog/browser-rum and its transitive deps.
libs/ledgerjs/packages/types-live/src/feature.ts Adds lldDatadog feature flag type definition.
libs/ledger-live-common/src/featureFlags/defaultFeatures.ts Adds default params for lldDatadog.
libs/client-ids/src/store/types.ts Adds userId/datadogId to identities state + dummy placeholders/helpers.
libs/client-ids/src/store/slice.ts Loads/persist/migrates userId/datadogId; adds init actions.
libs/client-ids/src/store/selectors.ts Adds selectors for userId and datadogId.
libs/client-ids/src/store/persistence.ts Persists userId/datadogId (omits dummy values).
libs/client-ids/src/store/persistence.test.ts Tests persistence behavior for new IDs.
libs/client-ids/src/store/middleware.ts Changes sync gating to depend on userId being non-dummy.
libs/client-ids/src/store/middleware.test.ts Updates middleware tests to use initFromScratch vs async getUserId.
libs/client-ids/src/store/index.ts Re-exports selectors.
libs/client-ids/src/ids/index.ts Exports new ID wrappers.
libs/client-ids/src/ids/UserId.ts Introduces UserId wrapper with redacted toString/toJSON.
libs/client-ids/src/ids/DatadogId.ts Introduces DatadogId wrapper + allowlisted export methods.
libs/client-ids/src/ids/DatadogId.test.ts Adds unit tests for DatadogId.
libs/client-ids/export-rules.json Updates allowlist rules for new export methods.
apps/ledger-live-desktop/tools/rspack/utils.ts Loads .env* files and injects Datadog globals in builds.
apps/ledger-live-desktop/tools/dist/index.js Ensures Datadog env vars are passed into production/staging builds.
apps/ledger-live-desktop/tests/testSetup.tsx Exposes unmount in test render return type.
apps/ledger-live-desktop/tests/mocks/electron.ts Adjusts mocked ipcRenderer.invoke typing/behavior.
apps/ledger-live-desktop/src/state-manager/configureStore.ts Stops passing legacy getUserId to identities sync middleware.
apps/ledger-live-desktop/src/sentry/renderer.ts Switches Sentry user id to DatadogId from identities store.
apps/ledger-live-desktop/src/sentry/anonymizer.ts Makes electron IPC path lookup more defensive; adjusts path replace.
apps/ledger-live-desktop/src/sentry/anonymizer.test.ts Adds tests for anonymizer path replacement/recursion.
apps/ledger-live-desktop/src/renderer/screens/swapWeb/index.tsx Reports swap load error to both Sentry and Datadog.
apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/SwapWebViewDemo3.tsx Reports swap unavailable error to both Sentry and Datadog.
apps/ledger-live-desktop/src/renderer/reducers/settings.ts Notes sentryLogs flag is also used as Datadog opt-in.
apps/ledger-live-desktop/src/renderer/logger/index.ts Sends breadcrumbs/errors to Datadog alongside Sentry.
apps/ledger-live-desktop/src/renderer/logger/index.test.ts Adds unit tests for logger Datadog/Sentry calls.
apps/ledger-live-desktop/src/renderer/init.tsx Introduces identities initialization helper; updates Sentry init call signature.
apps/ledger-live-desktop/src/renderer/helpers/identities.ts Adds desktop identities initialization/migration logic.
apps/ledger-live-desktop/src/renderer/helpers/identities.test.ts Adds tests for identities init/migration paths.
apps/ledger-live-desktop/src/renderer/components/ConnectEnvsToDatadog.tsx Initializes Datadog (opt-in + feature flag) and syncs tags periodically.
apps/ledger-live-desktop/src/renderer/components/ConnectEnvsToDatadog.test.tsx Adds tests for Datadog init + tag syncing + cleanup.
apps/ledger-live-desktop/src/renderer/App.tsx Wires ConnectEnvsToDatadog into app providers tree.
apps/ledger-live-desktop/src/main/setup.ts Captures crash test errors in Datadog path too; minor Node import cleanup.
apps/ledger-live-desktop/src/main/index.ts Initializes Datadog main forwarding based on persisted datadogId.
apps/ledger-live-desktop/src/datadog/renderer.ts Adds Datadog RUM init, IPC error ingestion, breadcrumbs/tags helpers.
apps/ledger-live-desktop/src/datadog/renderer.test.ts Adds tests for Datadog renderer wrapper behavior.
apps/ledger-live-desktop/src/datadog/main.ts Adds main-process error capture/forwarding to renderer.
apps/ledger-live-desktop/src/datadog/main.test.ts Adds tests for Datadog main forwarding and gating.
apps/ledger-live-desktop/src/datadog/ignoreErrors.ts Ports Sentry-like ignore list for Datadog filtering.
apps/ledger-live-desktop/src/datadog/ignoreErrors.test.ts Adds tests for ignore list matcher.
apps/ledger-live-desktop/src/datadog/config.ts Adds Datadog build config accessor + beforeSend anonymization/filtering.
apps/ledger-live-desktop/src/datadog/config.test.ts Adds tests for Datadog config and beforeSend.
apps/ledger-live-desktop/package.json Adds @datadog/browser-rum dependency.
apps/ledger-live-desktop/jest.config.js Adds Datadog globals for tests.
apps/ledger-live-desktop/index-types.d.ts Declares Datadog build-time globals.
apps/ledger-live-desktop/.eslintrc.js Marks Datadog globals as readonly for ESLint.
apps/ledger-live-desktop/.env.staging Adds Datadog RUM env vars for staging.
apps/ledger-live-desktop/.env.production Adds Datadog RUM env vars for production.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +4 to +7
jest.mock("~/sentry/renderer", () => ({
captureException: jest.fn(),
captureBreadcrumb: jest.fn(),
}));
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

~/sentry/renderer is already mocked globally in apps/ledger-live-desktop/tests/jestSetup.js (as src/sentry/renderer). Re-mocking it here can cause mock cannibalization/flakiness with parallel Jest workers. Prefer using the global mock and only configure return values/expectations via jest.mocked(...) in beforeEach.

Copilot generated this review using guidance from repository custom instructions.
Comment on lines +19 to +22
jest.mock("~/renderer/experimental", () => ({
enabledExperimentalFeatures: jest.fn(() => []),
}));

Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test file mocks ~/renderer/experimental twice; the first mock is immediately overridden by the second. Consolidating into a single jest.mock will make the test setup clearer and avoid confusion about which implementation is active.

Suggested change
jest.mock("~/renderer/experimental", () => ({
enabledExperimentalFeatures: jest.fn(() => []),
}));

Copilot uses AI. Check for mistakes.
"test-deep-links": "ws --spa ledger-live-desktop-deeplinks.html"
},
"dependencies": {
"@datadog/browser-rum": "6.27.1",
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR introduces a new desktop feature/instrumentation path and adds a new dependency (@datadog/browser-rum). Per repo policy, user-facing behavior and library/API changes should include a Changeset (pnpm changeset). No Datadog-related changeset appears to be present under .changeset/ — please add one.

Suggested change
"@datadog/browser-rum": "6.27.1",

Copilot uses AI. Check for mistakes.
Comment on lines +40 to 44
* Optional: resolve userId (e.g. from legacy app user). Used by mobile until it migrates to identities store.
* Desktop uses identities state only and does not pass this.
*/
getUserId?: (state: State) => Promise<string>;
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SyncMiddlewareConfig still exposes getUserId, but the middleware never calls it anymore and also short-circuits syncing when userId is dummy. This breaks current mobile usage (mobile configureStore passes getUserId and may keep identities userId dummy), so push-devices sync will never run. Either remove getUserId everywhere, or (preferred for backward compatibility) when userId is dummy and getUserId is provided, resolve it and dispatch an action (e.g., importFromLegacy / initFromScratch) before proceeding with sync.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +17
if (persisted) {
store.dispatch(identitiesSlice.actions.initFromPersisted(persisted));
return false;
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When persisted app/identities exists (older versions only persisted device IDs), this function returns immediately after initFromPersisted, leaving userId/datadogId as the dummy placeholders. That prevents push-devices sync (dummy userId) and prevents Datadog user identification. After loading persisted identities, consider migrating missing IDs (try legacy app/user / localStorage, otherwise generate via initFromScratch or a dedicated “ensureIds” action) before returning.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure i understand this feedback. if it's imported from existing app.identities, it can't be dummy

@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch from 30d2f1d to c8f910f Compare March 2, 2026 15:02
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch 2 times, most recently from db01ae9 to 0b8ee4b Compare March 2, 2026 18:21
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch from 4fed259 to c0432a2 Compare March 3, 2026 11:48
@live-github-bot live-github-bot bot removed common Has changes in live-common ledgerjs Has changes in the ledgerjs open source libs labels Mar 3, 2026
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch 4 times, most recently from 7c12cd7 to 5fca434 Compare March 3, 2026 15:21
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch 3 times, most recently from c0d044b to ca790ec Compare March 5, 2026 08:16
@gre-ledger gre-ledger requested a review from Copilot March 5, 2026 08:16
@vercel
Copy link

vercel bot commented Mar 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
ledger-live-github-bot Ignored Ignored Preview Mar 5, 2026 8:57am
native-ui-storybook Ignored Ignored Preview Mar 5, 2026 8:57am
react-ui-storybook Ignored Ignored Preview Mar 5, 2026 8:57am

Request Review

@live-github-bot live-github-bot bot added mobile Has changes in LLM common Has changes in live-common coin-modules shared-lib Label added for automated tagging of PRs and removed automation CI/CD stuff labels Mar 5, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 62 out of 65 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +152 to +158
<<<<<<< HEAD
sentry(() => sentryLogsSelector(store.getState()));
=======
// Initialize identities before Sentry so setUser gets the real datadogId (not dummy) when available
await initIdentities(store);
sentry(() => sentryLogsSelector(store.getState()), store);
>>>>>>> c0d044b41a (feat(desktop): add Datadog RUM and build tooling)
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are unresolved merge conflict markers (<<<<<<< HEAD, =======, >>>>>>> c0d044b41a) left in this file. This will cause a syntax error at runtime and the app will not start. The conflict between the two versions of the sentry(...) call and initIdentities must be resolved before merging.

Suggested change
<<<<<<< HEAD
sentry(() => sentryLogsSelector(store.getState()));
=======
// Initialize identities before Sentry so setUser gets the real datadogId (not dummy) when available
await initIdentities(store);
sentry(() => sentryLogsSelector(store.getState()), store);
>>>>>>> c0d044b41a (feat(desktop): add Datadog RUM and build tooling)
// Initialize identities before Sentry so setUser gets the real datadogId (not dummy) when available
await initIdentities(store);
sentry(() => sentryLogsSelector(store.getState()), store);

Copilot uses AI. Check for mistakes.
pnpm-lock.yaml Outdated
Comment on lines +41449 to +41452
'@grpc/grpc-js@1.7.3':
dependencies:
'@grpc/proto-loader': 0.7.15
'@types/node': 22.19.13
'@types/node': 24.10.13
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lockfile shows @types/node resolved version changing from 22.19.13 to 24.10.13 across dozens of transitive entries. None of the package.json changes in this PR modify @types/node. Per repo guidelines, the lockfile diff should be scoped to what was actually changed. Please regenerate the lockfile from a clean pnpm install to ensure only the intended dependency changes (@datadog/browser-rum, uuid, and test tooling) remain.

Copilot generated this review using guidance from repository custom instructions.
"<!DOCTYPE html",
"Unexpected ''",
"Unexpected '<'",
"Service Unvailable",
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Service Unvailable" is misspelled — it should be "Service Unavailable". This typo is also present in the Sentry ignore list (sentry/install.ts:56), so you may want to fix it in both places to correctly catch "503 Service Unavailable" error messages.

Suggested change
"Service Unvailable",
"Service Unavailable",

Copilot uses AI. Check for mistakes.
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch from ca790ec to 99cf185 Compare March 5, 2026 08:28
@live-github-bot live-github-bot bot added automation CI/CD stuff and removed mobile Has changes in LLM common Has changes in live-common coin-modules labels Mar 5, 2026
feat(client-ids): add UserId and DatadogId ID classes

Add UserId and DatadogId with redaction, export* methods, and export-rules.
DeviceId.exportDeviceIdForPersistence allowlist trimmed to persistence only.

feat(client-ids): add userId and datadogId to identities store

Extend IdentitiesState with userId/datadogId (dummy placeholders).
Slice: initFromPersisted, importFromLegacy, initFromScratch.
Persistence and sync middleware use identities state; optional getUserId for mobile.

fix: ignore build and generated folders in client-ids script

feat(desktop): unified identities migrated from legacy storage

test(e2e): add identities migration test

chore: extend cursor and github rules to mention client-ids paradigm

feat(desktop): use datadogId from identities in Sentry

Sentry renderer init takes store and sets user id via datadogIdSelector.

fix(desktop): omit userId when outside Redux context (crash screen)

ExportLogsButton and RenderError can render without a Redux Provider
(e.g. AppError crash screen). Use ReactReduxContext to detect store;
when missing, render ExportLogsBtnWithoutStore and omit userAnonymousId
from export meta. Conditionally render Hard Reset block in RenderError
only when hasStore to avoid store-dependent UI outside Provider.
- Datadog RUM: config, main process (init from db), renderer, ConnectEnvsToDatadog, ignoreErrors.
- Main: read identities/datadogId from db and init Datadog when present.
- Logger: forward to Datadog captureException when enabled.
- Env, jest, eslint, rspack, sourcemaps, testSetup unmount type, pnpm-lock.
@gre-ledger gre-ledger force-pushed the support/desktop-datadog branch from 99cf185 to adbd318 Compare March 5, 2026 08:57
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
77.3% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation CI/CD stuff desktop Has changes in LLD shared-lib Label added for automated tagging of PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants